package top.bug.blog.utils;

import java.util.regex.Pattern;

/**
 * @author <a href="https://github.com/jiusi66">九思.</a>
 * @email 10837907@qq.com
 * @from <a href="https://www.52bug.top">递归茶馆-www.52bug.top</a>
 * Markdown文本清洗工具类
 * 用于去除Markdown语法，提取纯文本内容，减少AI处理时的token消耗
 */
public class MarkdownCleaner {

    /**
     * 正则表达式模式预编译
     */
    private static final Pattern HEADER_PATTERN = Pattern.compile("^#{1,6}\\s*", Pattern.MULTILINE);
    private static final Pattern BOLD_PATTERN = Pattern.compile("\\*\\*(.*?)\\*\\*|__(.*?)__");
    private static final Pattern ITALIC_PATTERN = Pattern.compile("\\*(.*?)\\*|_(.*?)_");
    private static final Pattern STRIKETHROUGH_PATTERN = Pattern.compile("~~(.*?)~~");
    private static final Pattern CODE_BLOCK_PATTERN = Pattern.compile("```[\\s\\S]*?```", Pattern.MULTILINE);
    private static final Pattern INLINE_CODE_PATTERN = Pattern.compile("`([^`]*)`");
    private static final Pattern LINK_PATTERN = Pattern.compile("\\[([^\\]]*)\\]\\([^)]*\\)");
    private static final Pattern IMAGE_PATTERN = Pattern.compile("!\\[([^\\]]*)\\]\\([^)]*\\)");
    private static final Pattern BLOCKQUOTE_PATTERN = Pattern.compile("^>\\s*", Pattern.MULTILINE);
    private static final Pattern LIST_PATTERN = Pattern.compile("^[\\*\\+\\-]\\s*|^\\d+\\.\\s*", Pattern.MULTILINE);
    private static final Pattern TABLE_PATTERN = Pattern.compile("\\|.*?\\|\\s*\\n?\\|?\\s*:?[-]+", Pattern.MULTILINE);
    private static final Pattern HR_PATTERN = Pattern.compile("^[-*_]{3,}\\s*$", Pattern.MULTILINE);
    private static final Pattern MULTIPLE_NEWLINES = Pattern.compile("\\n{3,}");
    private static final Pattern EXTRA_SPACES = Pattern.compile("\\s{2,}");
    private static final Pattern HTML_TAGS = Pattern.compile("<[^>]*>");

    /**
     * 清洗Markdown文本，去除所有Markdown语法
     *
     * @param markdown 原始Markdown文本
     * @return 清洗后的纯文本
     */
    public static String cleanMarkdown(String markdown) {
        if (markdown == null || markdown.trim().isEmpty()) {
            return "";
        }

        String cleaned = markdown;

        // 按顺序应用清洗规则
        cleaned = removeCodeBlocks(cleaned);
        cleaned = removeImages(cleaned);
        cleaned = removeLinks(cleaned);
        cleaned = removeHeaders(cleaned);
        cleaned = removeBoldAndItalic(cleaned);
        cleaned = removeStrikethrough(cleaned);
        cleaned = removeBlockquotes(cleaned);
        cleaned = removeLists(cleaned);
        cleaned = removeTables(cleaned);
        cleaned = removeHorizontalRules(cleaned);
        cleaned = removeInlineCode(cleaned);
        cleaned = removeHtmlTags(cleaned);
        cleaned = normalizeWhitespace(cleaned);

        return cleaned.trim();
    }

    /**
     * 清洗Markdown文本，但保留段落结构
     *
     * @param markdown 原始Markdown文本
     * @return 保留段落结构的纯文本
     */
    public static String cleanMarkdownKeepParagraphs(String markdown) {
        if (markdown == null || markdown.trim().isEmpty()) {
            return "";
        }

        String cleaned = markdown;

        // 移除代码块、图片、链接等
        cleaned = removeCodeBlocks(cleaned);
        cleaned = removeImages(cleaned);
        cleaned = removeLinks(cleaned);
        cleaned = removeBoldAndItalic(cleaned);
        cleaned = removeStrikethrough(cleaned);
        cleaned = removeInlineCode(cleaned);
        cleaned = removeHtmlTags(cleaned);

        // 保留段落换行，但清理其他格式
        cleaned = HEADER_PATTERN.matcher(cleaned).replaceAll("");
        cleaned = BLOCKQUOTE_PATTERN.matcher(cleaned).replaceAll("");
        cleaned = LIST_PATTERN.matcher(cleaned).replaceAll("");
        cleaned = TABLE_PATTERN.matcher(cleaned).replaceAll("");
        cleaned = HR_PATTERN.matcher(cleaned).replaceAll("");

        cleaned = normalizeWhitespace(cleaned);

        return cleaned.trim();
    }

    /**
     * 轻度清洗，只移除代码块、表格等复杂结构，保留基本格式
     *
     * @param markdown 原始Markdown文本
     * @return 轻度清洗后的文本
     */
    public static String cleanMarkdownLight(String markdown) {
        if (markdown == null || markdown.trim().isEmpty()) {
            return "";
        }

        String cleaned = markdown;

        // 只移除最占用token的元素
        cleaned = removeCodeBlocks(cleaned);
        cleaned = removeTables(cleaned);
        cleaned = removeImages(cleaned);
        cleaned = removeHtmlTags(cleaned);
        cleaned = normalizeWhitespace(cleaned);

        return cleaned.trim();
    }

    // 具体的清洗方法
    private static String removeHeaders(String text) {
        return HEADER_PATTERN.matcher(text).replaceAll("");
    }

    private static String removeBoldAndItalic(String text) {
        text = BOLD_PATTERN.matcher(text).replaceAll("$1$2");
        text = ITALIC_PATTERN.matcher(text).replaceAll("$1$2");
        return text;
    }

    private static String removeStrikethrough(String text) {
        return STRIKETHROUGH_PATTERN.matcher(text).replaceAll("$1");
    }

    private static String removeCodeBlocks(String text) {
        return CODE_BLOCK_PATTERN.matcher(text).replaceAll("");
    }

    private static String removeInlineCode(String text) {
        return INLINE_CODE_PATTERN.matcher(text).replaceAll("$1");
    }

    private static String removeLinks(String text) {
        return LINK_PATTERN.matcher(text).replaceAll("$1");
    }

    private static String removeImages(String text) {
        return IMAGE_PATTERN.matcher(text).replaceAll("$1");
    }

    private static String removeBlockquotes(String text) {
        return BLOCKQUOTE_PATTERN.matcher(text).replaceAll("");
    }

    private static String removeLists(String text) {
        return LIST_PATTERN.matcher(text).replaceAll("");
    }

    private static String removeTables(String text) {
        return TABLE_PATTERN.matcher(text).replaceAll("");
    }

    private static String removeHorizontalRules(String text) {
        return HR_PATTERN.matcher(text).replaceAll("");
    }

    private static String removeHtmlTags(String text) {
        return HTML_TAGS.matcher(text).replaceAll("");
    }

    private static String normalizeWhitespace(String text) {
        text = MULTIPLE_NEWLINES.matcher(text).replaceAll("\n\n");
        text = EXTRA_SPACES.matcher(text).replaceAll(" ");
        return text;
    }

    /**
     * 获取清洗后的文本长度
     *
     * @param cleanedText 清洗后的文本
     * @return 文本长度
     */
    public static int getCleanedTextLength(String cleanedText) {
        return cleanedText != null ? cleanedText.length() : 0;
    }

    /**
     * 估算清洗前后的节省比例
     *
     * @param original 原始文本
     * @param cleaned  清洗后文本
     * @return 节省的比例（0-1之间）
     */
    public static double calculateSavingRatio(String original, String cleaned) {
        if (original == null || original.trim().isEmpty()) {
            return 0.0;
        }
        int originalLength = original.length();
        int cleanedLength = cleaned != null ? cleaned.length() : 0;

        return 1.0 - (double) cleanedLength / originalLength;
    }

    /**
     * 估算token减少数量（基于字符数简单估算）
     *
     * @param original 原始文本
     * @param cleaned  清洗后文本
     * @return 估计减少的token数量
     */
    public static int estimateTokenReduction(String original, String cleaned) {
        if (original == null) {
            return 0;
        }

        int originalLength = original.length();
        int cleanedLength = cleaned != null ? cleaned.length() : 0;

        // 简单估算：假设平均每个token 4个字符
        int originalTokens = originalLength / 4;
        int cleanedTokens = cleanedLength / 4;
        return Math.max(0, originalTokens - cleanedTokens);
    }

    /**
     * 获取清洗统计信息
     *
     * @param original 原始文本
     * @param cleaned  清洗后文本
     * @return 包含统计信息的字符串
     */
    public static String getCleaningStats(String original, String cleaned) {
        if (original == null) {
            return "无数据";
        }

        int originalLength = original.length();
        int cleanedLength = cleaned != null ? cleaned.length() : 0;
        double savingRatio = calculateSavingRatio(original, cleaned);
        int tokenReduction = estimateTokenReduction(original, cleaned);

        return String.format(
                "原始长度: %d 字符, 清洗后: %d 字符, 节省: %.2f%%, 估计减少token: %d",
                originalLength, cleanedLength, savingRatio * 100, tokenReduction
        );
    }
}